import { JSBridge } from "../JSBridge";
import OppoBannerUI from "./OppoBannerUI";
import ADBase, { BannerPos } from "../ADBase";
import SDKManager, { MaxCloseBannerTimes } from "../SDKManager";
import ScreenFit from "../../ScreenFit";
import { OppoConfig } from "./OppoConfig";
import QuLe, { ADType } from "../QuLe";

/** 持久化 */
const KEY_INSERTAD = 'KEY_INSERTAD';

/** 插屏广告信息结构 */
const enum EInsertADErr {
    eTooMuch, eCDErr
}
interface IInsertAD {
    num: number; //当天展示的次数
    date: string; //日期
    lastTime: number; //最近一次展示广告的时间戳
}

export default class OppoAD extends ADBase {

    //Banner广告条
    static bannerAD: any; //banner广告对象
    static data: any;
    private onBannerSuccessFunc: Function;
    private onBannerFailFunc: Function;
    private bannerUI: OppoBannerUI;
    private currBannerPos: BannerPos
    static readonly bannerUIWidth = 440;
    static readonly bannerUIHeight = 120;
    //激励视频广告
    private rewardVideoAD: any;
    private onRewardVideoClose: Function;
    // 插屏广告
    private insertADObj: any; //插屏广告对象
    private onInsertVideoClose: Function;

    //Banner广告开始=====================================================================================================
    /** 显示Banner广告
    * @param position 显示位置
    * @param loadNewAD 是否切换下一个广告内容，默认不换 
    */
    showBanner(position: BannerPos, loadNewAD = false) {
        if (SDKManager.disableAllADAfter5Shares) {
            console.log('玩家已分享5次,不再显示Banner广告')
            return;
        }
        //未创建UI，则等待创建UI完成后重新执行一次，已创建过UI则直接往下执行
        let created = this.checkAndCreateBannerUI(() => {
            //构建完UI后重新调用
            this.showBanner(position);
        });
        if (!created) {
            return;
        }
        this.setBannerPos(position);
        super.showBanner(position);
        this.currBannerPos = position;
        let qg = JSBridge.getQGObj();
        if (!qg) return;
        if (SDKManager.closeBannerTimes >= MaxCloseBannerTimes) {
            console.log("今天主动关闭次数过多，不再显示原生banner广告");
            return;
        }
        let bannerAD = OppoAD.bannerAD;
        if (bannerAD && loadNewAD) {
            OppoAD.bannerAD.destroy();
            bannerAD = null;
        }
        if (!bannerAD) {
            let bannerId = QuLe.instance.remoteConfig.bannerId;
            bannerAD = OppoAD.bannerAD = qg.createNativeAd({
                adUnitId: bannerId
            });
            console.log("创建新的banner广告对象: " + bannerId);
        }
        this.onBannerSuccessFunc = this.onBannerSuccess.bind(this);
        bannerAD.onLoad(() => {
            this.onBannerSuccessFunc && this.onBannerSuccessFunc();
            QuLe.instance.record(QuLe.PlatOppo, ADType.Banner);
        });
        this.onBannerFailFunc = this.onBannerFail.bind(this);
        bannerAD.onError(this.onBannerFail);
        //展示banner
        console.log('开始加载banner广告');
        bannerAD.load();
    }

    /** 设置Banner广告位置 */
    setBannerPos(position: BannerPos) {
        if (SDKManager.disableAllADAfter5Shares) {
            console.log('玩家已分享5次,不再显示Banner广告')
            return;
        }
        let screenSize = ScreenFit.screenSize;
        let bannerWidthHalf = this.bannerUI.node.width * 0.5;
        let bannerHeightHalf = this.bannerUI.node.height * 0.5;
        let iphoneXLiuHaiSize = screenSize.width * 0.05;
        switch (position) {
            case BannerPos.TopLeft:
                this.bannerUI.node.x = bannerWidthHalf + iphoneXLiuHaiSize;
                this.bannerUI.node.y = screenSize.height - bannerHeightHalf;
                break;
            case BannerPos.TopCenter:
                this.bannerUI.node.x = screenSize.width * 0.5;
                this.bannerUI.node.y = screenSize.height - bannerHeightHalf;
                break;
            case BannerPos.TopRight:
                this.bannerUI.node.x = screenSize.width - bannerWidthHalf - iphoneXLiuHaiSize;
                this.bannerUI.node.y = screenSize.height - bannerHeightHalf;
                break;
            case BannerPos.BottomLeft:
                this.bannerUI.node.x = bannerWidthHalf + iphoneXLiuHaiSize;
                this.bannerUI.node.y = bannerHeightHalf;
                break;
            case BannerPos.BottomCenter:
                this.bannerUI.node.x = screenSize.width * 0.5;
                this.bannerUI.node.y = bannerHeightHalf;
                break;
            case BannerPos.BottomRight:
                this.bannerUI.node.x = screenSize.width - bannerWidthHalf - iphoneXLiuHaiSize;
                this.bannerUI.node.y = bannerHeightHalf;
                break;
        }
        super.setBannerPos(position);
    }

    /** 关闭Banner广告 */
    hideBanner(byPlayerClick: boolean) {
        super.hideBanner(byPlayerClick);
        let bannerUI = this.bannerUI;
        if (bannerUI) {
            console.log('Banner广告隐藏')
            bannerUI.hide();
            //累计玩家主动关闭次数
            if (byPlayerClick) {
                SDKManager.closeBannerTimes += 1;
            }
        }
    }

    /** Banner成功显示时触发 */
    private onBannerSuccess(res): void {
        console.log('banner广告加载成功:' + JSON.stringify(res));
        if (0 == res.code && res.adList.length > 0) {
            let adData = OppoAD.data = res.adList[0];
            let bannerUI = this.bannerUI;
            if (bannerUI) {
                bannerUI.show(adData);
            }
            //上报广告点击
            OppoAD.bannerAD.reportAdShow({ adId: adData.adId });
        }
    }

    /** Banner显示失败时触发 */
    private onBannerFail(err): void {
        console.log('banner广告加载失败:' + JSON.stringify(err));
        if (OppoAD.bannerAD) {
            OppoAD.bannerAD.destroy();
            OppoAD.bannerAD = null;
        }
        setTimeout(() => {
            this.showBanner(this.currBannerPos); //延时重试
        }, 2000);
    }

    /** 检查并创佳BannerUI，已经创建过返回true，否等待创建回调后再执行别的逻辑 */
    private checkAndCreateBannerUI(onCreateFinish: Function): boolean {
        console.log('判断BannerUI是否已创建')
        if (!this.bannerUI) {
            console.log('BannerUI未创建，开始创建BannerUI')
            cc.loader.loadRes('textures/common/white2x2', cc.SpriteFrame, (err, white2x2) => {
                if (err) {
                    console.error('创建BannerUI失败，请在resources/textures/common目录下放置white2x2图片');
                    return;
                }
                //创建Banner
                let boardNode = new cc.Node();
                boardNode.setParent(cc.Canvas.instance.node.parent);
                cc.game.addPersistRootNode(boardNode);
                boardNode.width = OppoAD.bannerUIWidth;
                boardNode.height = OppoAD.bannerUIHeight;
                let bannerUI = this.bannerUI = boardNode.addComponent(OppoBannerUI);
                bannerUI.whiteTex = white2x2;
                //背景
                let bg = bannerUI.bg = new cc.Node().addComponent(cc.Sprite);
                bg.node.setParent(boardNode);
                bg.spriteFrame = white2x2;
                bg.sizeMode = cc.Sprite.SizeMode.CUSTOM;
                bg.node.width = boardNode.width;
                bg.node.height = boardNode.height;
                bg.node.color = cc.Color.WHITE;
                //广告两个字
                let ad: cc.Label = new cc.Node().addComponent(cc.Label);
                ad.node.setParent(boardNode);
                ad.node.x = 158;
                ad.node.y = 42;
                ad.node.color = cc.color(110, 110, 110);
                ad.string = '广告';
                ad.fontSize = ad.lineHeight = 22;
                //Icon
                let icon = bannerUI.icon = new cc.Node().addComponent(cc.Sprite);
                icon.node.setParent(boardNode);
                icon.node.x = -160;
                icon.node.y = 0;
                icon.node.width = icon.node.height = 100;
                icon.sizeMode = cc.Sprite.SizeMode.CUSTOM;
                //标题
                let title = bannerUI.title = new cc.Node().addComponent(cc.Label);
                title.node.setParent(boardNode);
                title.node.anchorX = 0;
                title.node.x = -102;
                title.node.y = 28;
                title.node.width = 230;
                title.node.height = 30;
                title.node.color = cc.color(0, 30, 155);
                title.horizontalAlign = cc.Label.HorizontalAlign.LEFT;
                title.fontSize = title.lineHeight = 25;
                title.string = '广告标题'
                //描述
                let desc = bannerUI.desc = new cc.Node().addComponent(cc.Label);
                desc.node.setParent(boardNode);
                desc.node.x = title.node.x;
                desc.node.y = 3;
                desc.node.anchorX = 0;
                desc.node.anchorY = 1;
                desc.node.width = 270;
                desc.node.height = 55;
                desc.node.color = cc.color(80, 80, 80);
                desc.horizontalAlign = cc.Label.HorizontalAlign.LEFT;
                desc.verticalAlign = cc.Label.VerticalAlign.TOP;
                desc.fontSize = 20;
                desc.lineHeight = 25;
                desc.overflow = cc.Label.Overflow.RESIZE_HEIGHT;
                desc.string = '这是一个测试的广告内容，查看排版情况';
                //关闭按钮
                let btnClose = bannerUI.btnClose = new cc.Node();
                btnClose.setParent(boardNode);
                btnClose.addComponent(cc.Sprite).spriteFrame = white2x2;;
                btnClose.x = 205;
                btnClose.y = 45;
                btnClose.width = btnClose.height = 30;
                btnClose.color = cc.color(138, 138, 138);
                let x: cc.Label = new cc.Node().addComponent(cc.Label);
                x.node.setParent(btnClose);
                x.fontSize = x.lineHeight = 25;
                x.string = 'X';
                //初始化
                bannerUI.init();
                //结束
                onCreateFinish();
            });
            return false;
        }
        return true;
    }
    //Banner广告结束=====================================================================================================

    //激励视频广告开始=====================================================================================================
    /** 展示激励视频广告
     * onVideoClose(isEnded:boolean)
     */
    showRewardVideo(onClose?: Function): void {
        super.showRewardVideo(onClose);
        let qg = JSBridge.getQGObj();
        if (!qg) return;
        let videoAD = this.rewardVideoAD;
        if (!videoAD) {
            videoAD = this.rewardVideoAD = qg.createRewardedVideoAd({
                adUnitId: QuLe.instance.remoteConfig.videoId
            });
            if (!videoAD) {
                return;
            }
        }
        this.registVideoCallback();
        this.onRewardVideoClose = onClose;
        console.log("开始加载激励视频广告");
        videoAD.load();
    }

    /** 注册视频广告各种回调 */
    private registVideoCallback(): void {
        let videoAD = this.rewardVideoAD;
        if (!videoAD) return;
        videoAD.onLoad(function () {
            QuLe.instance.record(QuLe.PlatOppo, ADType.Video);
            videoAD.show();
        });
        videoAD.onClose((res) => {
            if (this.onRewardVideoClose) {
                this.onRewardVideoClose(res.isEnded);
            }
        });
        console.log("激励视频回调注册完成");
    }
    //激励视频广告结束=====================================================================================================

    //插屏广告开始=========================================================================================================
    /** 展示插屏广告 */
    showInsertAD(onClose?: Function): void {
        super.showInsertAD(onClose);
        if (SDKManager.disableAllADAfter5Shares) {
            console.log('玩家已分享5次,不再显示插屏广告')
            onClose && onClose();
            return;
        }
        let qg = JSBridge.getQGObj();
        if (!qg) {
            onClose && onClose();
            return;
        }
        this.onInsertVideoClose = onClose;
        let info = this.getInserADInfo();
        let errCode;
        if (info.num >= 8) { //次数达到上限
            errCode = EInsertADErr.eTooMuch;
        }
        else if ((info.lastTime + 60 * 1000) > Date.now()) { //cd不到60s
            errCode = EInsertADErr.eCDErr;
        }
        if (errCode) {
            console.log('插屏广告展示失败：' + errCode);
            this.onInsertVideoClose && this.onInsertVideoClose();
            return;
        }
        let insertADObj = this.insertADObj;
        if (!insertADObj) {
            insertADObj = qg.createInsertAd({
                adUnitId: QuLe.instance.remoteConfig.insertId
            });
        }
        insertADObj.onLoad(() => {
            console.log("插屏广告加载成功");
            insertADObj.show();
        });
        let _this = this;
        insertADObj.onShow(() => {
            console.log("插屏广告显示成功");
            QuLe.instance.record(QuLe.PlatOppo, ADType.Insert);
            let info = this.addNumInsertAD(1); //累计一次显示次数
            console.log(`${info.date} 显示插屏广告次数: ${info.num}`);
        });
        insertADObj.onError((err) => {
            console.log(`插屏广告发生错误： ${JSON.stringify(err)}`);
            _this.onInsertVideoClose && _this.onInsertVideoClose();
        });
        insertADObj.onClose(() => {
            console.log("插屏广告关闭");
            _this.onInsertVideoClose && _this.onInsertVideoClose();
        });
        console.log("开始加载插屏广告");
        insertADObj.load();
    }

    /** 获取当天玩家展示插屏广告的信息 */
    private getInserADInfo(): IInsertAD {
        let obj = this.insertADStorage;
        if (!obj) {
            obj = { num: 0, date: new Date().toDateString(), lastTime: 0 };
            this.insertADStorage = obj;
            return obj;
        }
        else {
            let nowDate = new Date().toDateString();
            if (obj.date == nowDate) {
                return obj;
            }
            else { //不是同一天，重置次数
                obj.date = nowDate;
                obj.num = 0;
                obj.lastTime = 0;
                this.insertADStorage = obj;
                return obj;
            }
        }
    }

    /** 增加玩家当天展示插屏广告的次数 */
    private addNumInsertAD(addNum: number): IInsertAD {
        let obj = this.getInserADInfo();
        obj.num += addNum;
        obj.lastTime = Date.now();
        this.insertADStorage = obj;
        return obj;
    }
    /** 获取缓存的IInsertAD */
    private get insertADStorage(): IInsertAD {
        let str = localStorage.getItem(KEY_INSERTAD);
        if (str) {
            return JSON.parse(str);
        }
        return null;
    }
    /** 存储IInsertAD */
    private set insertADStorage(insertAD: IInsertAD) {
        localStorage.setItem(KEY_INSERTAD, JSON.stringify(insertAD));
    }
    //插屏广告结束=========================================================================================================

}
